package singleton;

/**
 * 懒汉式
 * 唯一缺点: 存在线程不安全问题
 * 可以通过synchronized来解决,但是效率也下来了,锁优化
 */
public class Mgr05 {

    //双重检查,需不需要加volatile?
    //要加,问题要出在指令重排序上
    private static volatile Mgr05 INSTANCE;

    private Mgr05() {};

    public static Mgr05 getInstance() {
        if(null == INSTANCE){
            synchronized (Mgr05.class){     //双重检查,解决问题
                if(null == INSTANCE){
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    //此处是有3个指令
                    //1.申请内存 2.成员变量初始化 3.把内存的内容赋值给INSTANCE
                    //当发生指令重排时可能会把顺序调整为132,所以存在问题,当发生指令重拍第一个线程执行完此处还未执行2(整个步骤还未完成)接着第二个线程来会直接判断INSTANCE不为NULL返回,就存在问题
                    //通过volatile排除指令重排
                    INSTANCE = new Mgr05();
                }
            }
        }
        return INSTANCE;
    }

    public void m() {
        System.out.println("m");
    }

    public static void main(String[] args) {
        for(int i = 0; i < 100; i++){
            new Thread(() -> System.out.println(Mgr05.getInstance().hashCode())).start();
        }
    }

}
